package org.mtmi.ui;

import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.mtmi.tuio.listeners.DoubleTapListener;
import org.mtmi.tuio.listeners.DragListener;
import org.mtmi.tuio.listeners.SingleTapListener;
import org.mtmi.tuio.listeners.TUIODragEvent;
import org.mtmi.tuio.listeners.TUIOTapEvent;
import org.mtmi.ui.controls.ITouchableControl;
import org.mtmi.ui.scenes.Scene;


/**
 * Class to handle interaction with a given scene base on mouse usage.
 * 
 * @author jgout
 *
 */
public class MouseInteractionManager implements MouseListener, MouseMoveListener {

	private Scene scene;
	private ITouchableControl controlTapped;
	private Point tapPosition;

	public MouseInteractionManager() {
	}
	
	public void setScene( Scene s ) {
		if( scene!=null ) {
			scene.removeMouseListener( this );
			scene.removeMouseMoveListener( this );
		} 
		scene = s;
		if( scene!=null ) {
			scene.addMouseListener( this );
			scene.addMouseMoveListener( this );
		} 
	}

	private ITouchableControl getTouchableControl(MouseEvent e) {
		Control c = (Control) e.widget;
		//Point point = c.toDisplay(new Point(e.x, e.y));
		Rectangle b = ((Composite)c).getClientArea();
		float cx = e.x/(float)b.width;
		float cy = e.y/(float)b.height;
		return scene.getTouchableControl( cx, cy );
	}
	
	@Override
	public void mouseDoubleClick(MouseEvent e) {
		//DBLE click is desactivated due to time introduced for dblclick which interfere with midi timed notes...
		/*ITouchableControl control = getTouchableControl(e);
		if(control != null) {
			if(control instanceof DoubleTapListener) {
				((DoubleTapListener)control).doubleTap(new TUIOTapEvent(e.x, e.y));
			}
		}*/
	}

	@Override
	public void mouseDown(MouseEvent e) {
		ITouchableControl control = getTouchableControl(e);
		if(control != null) {
			if(control instanceof SingleTapListener) {
				controlTapped = control;
				tapPosition = new Point(e.x, e.y);
				Rectangle b = ((Composite)e.widget).getClientArea();
				float cx = e.x/(float)b.width;
				float cy = e.y/(float)b.height;
				((SingleTapListener)control).tapDown(new TUIOTapEvent( cx, cy, e.x, e.y ));
			}
		}
	}

	@Override
	public void mouseUp(MouseEvent e) {
		//use same control as the one tapped down:
		//ITouchableControl control = getTouchableControl(e);
		ITouchableControl control = controlTapped;
		if(control != null) {
			if(control instanceof SingleTapListener) {
				Rectangle b = ((Composite)e.widget).getClientArea();
				float cx = e.x/(float)b.width;
				float cy = e.y/(float)b.height;
				((SingleTapListener)control).tapUp(new TUIOTapEvent( cx,cy, e.x, e.y ));
				controlTapped = null;
				tapPosition = null;
			}
		}
	}

	@Override
	public void mouseMove(MouseEvent e) {
		if (controlTapped != null) {
			//TUIO simulator send drag event even if mouse is outside control bounds.
			//ITouchableControl control = getTouchableControl(e);
			//if (control != null && control == controlTapped) {
			ITouchableControl control = controlTapped;
				if (control instanceof DragListener) {
					//int x = e.x - tapPosition.x;
					//int y = e.y - tapPosition.y;
					//raw values:
					Rectangle b = ((Composite)e.widget).getClientArea();
					float cx = e.x/(float)b.width;
					float cy = e.y/(float)b.height;
					TUIODragEvent event = new TUIODragEvent( cx,cy, e.x, e.y );
					((DragListener) control).drag(event);
				}
			//}
		}
	}
}
